package org.xjc.aop;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.xjc.annotation.RequirePerm;
import org.xjc.config.RequestVariable;
import org.xjc.service.ErrorLogService;
import org.xjc.service.SecurityMenuService;
import org.xjc.service.SecurityUserService;
import org.xjc.vo.RespBean;
import springfox.documentation.spi.service.contexts.SecurityContext;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @Author : XJC
 * @Description : Error aop
 * @create : 2022/7/25 17:33
 */
@Order(1)
@Aspect
@Component
public class PermAspect {

    @Resource
    ErrorLogService errorLogService;

    public PermAspect() {
    }

    @Pointcut("@annotation(org.xjc.annotation.RequirePerm)")
    public void errorAspect() {
    }

    @Around("errorAspect()")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        RequirePerm requerPerm = null;

        try {
            try {
                requerPerm = getRequirePermData(joinPoint);
            } catch (Exception var5) {
                var5.printStackTrace();
            }
            if (requerPerm==null){
                return joinPoint.proceed();
            }

            //需要的权限
            List<String> permList=null;
            if (requerPerm.permList().length>0){
                //初始化权限
                permList= Arrays.asList(requerPerm.permList());
            }else {
                permList=new ArrayList<>();
            }
            if (!StringUtils.isBlank(requerPerm.perm())){
                permList.add(requerPerm.perm());
            }
            //用户的权限
            List<String> userPerm= RequestVariable.getRequestData().getUserPerm();
            if (permList.size()>0){
                //鉴权，无权限报错返回
                if (userPerm==null||userPerm.size()<1){
                    //用户权限有无初始化
                    return RespBean.error("权限不足");
                }
                for (String perm:permList){
                    if (userPerm.contains(perm)){
                        return joinPoint.proceed();
                    }
                }
                return RespBean.error("权限不足");
            }
            return joinPoint.proceed();
        } catch (Throwable var6) {
            String throwable="";
            if (var6 instanceof Exception) {
                throwable = getStackTrace((Exception) var6);
            } else {
                throwable = var6.toString();
            }
            try {
                errorLogService.saveErrorLog("requirePerm", getMethod(joinPoint).toString(), getParamData(joinPoint).toString()
                        , new Date(), throwable, "requirePerm");
            }catch (Exception e){
                return RespBean.error("错误");
            }
            return RespBean.error("权限不足");
        }
    }

    public static RequirePerm getRequirePermData(JoinPoint joinPoint) throws Exception {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        return method.getAnnotation(RequirePerm.class);
    }

    public static Method getMethod(JoinPoint joinPoint) throws Exception {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        return signature.getMethod();
    }

    public static Map<String, Object> getParamData(JoinPoint joinPoint) throws Exception {
        Map<String, Object> param = new HashMap();
        Object[] paramValues = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();

        for (int i = 0; i < paramNames.length; ++i) {
            param.put(paramNames[i], paramValues[i]);
        }

        return param;
    }
    public static String getStackTrace(Exception e) {
        StringBuffer message = new StringBuffer();
        StackTraceElement[] exceptionStack = e.getStackTrace();
        message.append(e.toString());

        for (StackTraceElement ste : exceptionStack) {
            message.append("at " + ste);
        }
        return message.toString();
    }

}